<?php

set_include_path(implode(PATH_SEPARATOR,
    array(
        get_include_path(),
        dirname(dirname(dirname(__FILE__)))
    )));

require_once 'tests/simpletest/autorun.php';

require_once 'database_engine/common_engine.php';

require_once 'database_engine/mysql_engine.php';

class MySqlConnectionTest extends UnitTestCase
{
    private function GetTestDatabaseOptions()
    {
        return array(
            ConnectionOption::Host => 'localhost',
            ConnectionOption::DatabaseName => 'test',
            ConnectionOption::Port => 3306,
            ConnectionOption::Login => 'root',
            ConnectionOption::Password => 'root'
        );
    }

    /**
     * @param array|null $connectionOptions
     * @return MySqlConnection
     */
    private function CreateConnection($connectionOptions = null)
    {
        return new MySqlConnection(isset($connectionOptions) ?
                $connectionOptions :
                $this->GetTestDatabaseOptions()
        );
    }

    public function testConnect()
    {
        $connection = $this->CreateConnection();
        $connection->Open();

        $this->assertTrue($connection->Opened());

        $connection->Close();
    }

    public function _testConnectFailOnConnectToServer()
    {
        $connectionOptions = $this->GetTestDatabaseOptions();
        $connectionOptions[ConnectionOption::Host] = 'not_exists_host';
        
        $connection = $this->CreateConnection($connectionOptions);

        $exceptionRaised = false;

        try
        {
            $connection->Open();
        }
        catch(Exception $e)
        {
            $exceptionRaised = true;
            $this->assertEqual('ConnectionFailedException', get_class($e));
        }

        $this->assertTrue($exceptionRaised);
        $this->assertFalse($connection->Opened());

        $connection->Close();
    }

    public function _testConnectFailOnConnectToDatabase()
    {
        $connectionOptions = $this->GetTestDatabaseOptions();
        $connectionOptions[ConnectionOption::DatabaseName] = 'not_exists_database';

        $connection = $this->CreateConnection($connectionOptions);

        $exceptionRaised = false;

        try
        {
            $connection->Open();
        }
        catch(Exception $e)
        {
            $exceptionRaised = true;
            $this->assertEqual('ConnectionFailedException', get_class($e));
        }

        $this->assertTrue($exceptionRaised);
        $this->assertFalse($connection->Opened());

        $connection->Close();
    }

    public function _testExecuteReader()
    {
        $connection = $this->CreateConnection();
        $connection->Open();

        $connection->ExecuteNoResult('DROP TABLE IF EXISTS pg_test_table');
        $connection->ExecuteNoResult(
            'CREATE TABLE pg_test_table (
              id       int AUTO_INCREMENT NOT NULL,
              `value`  varchar(20),
              PRIMARY KEY (id)
            ) ENGINE = InnoDB;'
        );

        $connection->ExecuteNoResult("INSERT INTO pg_test_table (`value`) VALUES ('value 1');");
        $connection->ExecuteNoResult("INSERT INTO pg_test_table (`value`) VALUES ('value 2');");

        $dataReader = $connection->ExecuteReader("SELECT * FROM pg_test_table");

        $this->assertNotNull($dataReader);

        $this->assertIdentical(array('id', 'value'), $dataReader->GetFieldNames());
        $this->assertTrue($dataReader->IsPrimaryKeyField('id'));
        $this->assertFalse($dataReader->IsPrimaryKeyField('value'));

        $this->assertTrue($dataReader->Next());

        $this->assertEqual(1, $dataReader->GetFieldValueByName('id'));
        $this->assertEqual('value 1', $dataReader->GetFieldValueByName('value'));

        $this->assertTrue($dataReader->Next());

        $this->assertEqual(2, $dataReader->GetFieldValueByName('id'));
        $this->assertEqual('value 2', $dataReader->GetFieldValueByName('value'));

        $this->assertFalse($dataReader->Next());
        
        $connection->Close();
    }

    private function PrepareTableWithRecords(IConnection $connection, $tableName)
    {
        $connection->ExecuteNoResult("DROP TABLE IF EXISTS $tableName");
        $connection->ExecuteNoResult(
            "CREATE TABLE $tableName (".
            ' id       int AUTO_INCREMENT NOT NULL,
              `value`  varchar(20),
              PRIMARY KEY (id)
            ) ENGINE = InnoDB;'
        );

        $connection->ExecuteNoResult("INSERT INTO $tableName (`value`) VALUES ('value 1');");
        $connection->ExecuteNoResult("INSERT INTO $tableName (`value`) VALUES ('value 2');");
    }

    public function testExecuteInvalidStatement()
    {
        $connection = $this->CreateConnection();
        $connection->Open();

        $this->expectException('SqlException');
        $connection->ExecuteReader("SELECT Error Statement");
    }

    public function testExceptionOnGetvalueWithoutNextCall()
    {
        $connection = $this->CreateConnection();
        $connection->Open();
        $this->PrepareTableWithRecords($connection, 'pg_test_error');

        $dataReader = $connection->ExecuteReader('SELECT * FROM pg_test_error');

        $this->expectException('SqlException');
        $dataReader->GetFieldValueByName('id');

        $dataReader->Next();

        $connection->Close();
    }

    public function testExceptionOnNotOpenedConnection()
    {
        $connection = $this->CreateConnection();

        $this->expectException('SqlException');
        $connection->ExecuteReader('SELECT * FROM pg_test_error');
    }
}

?>